package com.example.blockchain.init;

import com.example.blockchain.entity.block.Block;
import com.example.blockchain.entity.block.Friends;
import com.example.blockchain.entity.block.MapFriends;
import com.example.blockchain.entity.block.Node;
import com.example.blockchain.helper.SampleRepository;
import com.example.blockchain.utils.SQLManager;
import com.example.blockchain.utils.SQLiteHelper;
import io.ep2p.kademlia.NodeSettings;
import io.ep2p.kademlia.exception.UnsupportedBoundingException;
import io.ep2p.kademlia.netty.NettyKademliaDHTNode;
import io.ep2p.kademlia.netty.builder.NettyKademliaDHTNodeBuilder;
import io.ep2p.kademlia.netty.common.NettyConnectionInfo;
import io.ep2p.kademlia.node.KeyHashGenerator;
import io.ep2p.kademlia.node.external.ExternalNode;
import io.ep2p.kademlia.table.Bucket;
import io.ep2p.kademlia.table.RoutingTable;
import io.ep2p.kademlia.util.BoundedHashUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class ApplicationStartup implements CommandLineRunner {

    @Value("${bootstrap.ip}")
    private String bootstrapIp;

    @Value("${node.ip}")
    private String nodeIp;

    @Resource
    private Node node;

    @Resource
    private MapFriends map;
    @Resource
    private Block block;

    public NettyKademliaDHTNode<String, String> node2;


    @Override
    public void run(String... args) throws Exception {
        String localIP = nodeIp;
        System.out.println(localIP);

        KeyHashGenerator<BigInteger, String> keyHashGenerator = key -> {
            try {
                return new BoundedHashUtil(NodeSettings.Default.IDENTIFIER_SIZE).hash(key.hashCode(), BigInteger.class);
            } catch (UnsupportedBoundingException e) {
                e.printStackTrace();
            }
            return BigInteger.valueOf(key.hashCode());
        };
        NettyKademliaDHTNode<String, String> node1 = new NettyKademliaDHTNodeBuilder<>(
                BigInteger.valueOf(1L),
                new NettyConnectionInfo(bootstrapIp, 8883),
                new SampleRepository(),
                keyHashGenerator,
                String.class, String.class).build();
        // 创建引导节点

        // node 2
        int index = localIP.lastIndexOf(".");
        long myNodeId = Long.valueOf(localIP.substring(index + 1));
        node2= new NettyKademliaDHTNodeBuilder<>(
                BigInteger.valueOf(132),
                new NettyConnectionInfo(localIP, 24845),
                new SampleRepository(),
                keyHashGenerator,
                String.class, String.class).build();
        System.out.println("Bootstrapped? " + node2.start(node1).get(5, TimeUnit.SECONDS));
        Thread.sleep(5000);
        node.setNode(node2);
        RoutingTable<BigInteger, NettyConnectionInfo, Bucket<BigInteger, NettyConnectionInfo>> routingTable = node2.getRoutingTable();
        for (Bucket<BigInteger, NettyConnectionInfo> bucket : routingTable.getBuckets()) {
            List<BigInteger> nodeIds = bucket.getNodeIds();

            if (nodeIds.size() != 0) {
                for (BigInteger nodeId : nodeIds) {
                    ExternalNode<BigInteger, NettyConnectionInfo> nodeInfo = bucket.getNode(nodeId);
                    System.out.println(nodeInfo);
                    NettyConnectionInfo connectionInfo = nodeInfo.getConnectionInfo();
                    System.out.println(connectionInfo);
                    Friends f= map.getFs().get(connectionInfo.getHost());
                    if(f==null){
                        String ip=connectionInfo.getHost();
                        if(!ip.equals(localIP)){
                            Friends friends=new Friends();
                            friends.setIp(connectionInfo.getHost());
                            friends.setFriendliness(100);
                            map.getFs().put(ip,friends);
                        }

                    }
                }
            }
        }
        //block=new Block();
        dbInit();
    }



    private static void dbInit() throws SQLException {
        Connection connection = null;
        try {
            connection = SQLiteHelper.getConnection();
            connection.setAutoCommit(false);
            Statement statement = connection.createStatement();
            statement.executeUpdate(SQLManager.getPendingSql());
            statement.executeUpdate(SQLManager.getDicSql());
            connection.commit();

        } catch (Exception e) {
            if (connection != null)
                connection.rollback();
            e.getMessage();

        } finally {
            SQLiteHelper.close(connection);
        }
    }
}
